#include "Ataxx.h"


Ataxx::Ataxx(void) : Game() {
	m_gameName = "Ataxx";
}

Ataxx::Ataxx(int columns, int rows)  : Game(columns,rows) {
	m_gameName = "Ataxx";
}

Ataxx::~Ataxx(void)
{
}

std::string Ataxx::gameSpecialAction(const Move &gameMove) {
	std::stringstream stream;
	if(vectorDistance(gameMove,1)) {
		stream << Split << " ";
	}

	int victimPlayer;
	if(currentPlayer() == Player1){ 
		victimPlayer = Player2;
	}
	else {
		victimPlayer = Player1;
	}

	
	for(int i = -1 ; i <= 1 ; ++i ) {
		for(int j = -1 ; j <= 1 ; ++j ) {
			int occupyer = gameBoard().getOccupancy(gameMove.t_col+i,gameMove.t_row+j);
			if( occupyer != OffBoard && victimPlayer == occupyer) {
				stream << Spread << " ";
				stream << gameMove.t_col+i << " " << gameMove.t_row+j << " " << currentPlayer() << " ";
			}
		}
	}
	return stream.str();
}

void Ataxx::undoSpecialAction(std::stringstream &undoAction, std::stringstream &actionStr) {
	int action;

	while(actionStr >> action) {
		if(Split == action) {
			continue;
		}else if(Spread == action) {
			undoAction << action << " ";
			int col,row,claimer;
			actionStr >> col >> row >> claimer;
			//swap claimer
			if(Player1 == claimer) claimer = Player2;
			else claimer = Player1;
			undoAction << col << " " << row << " " << claimer << " ";
		}
	}
}

void Ataxx::doGameSpecialAction(std::stringstream &actionStream, const Move &gameMove) {
	int action, player, claimer;
	actionStream >> player;
	// Game handles player in string in base,
	// But ataxx handles player in string in derived while undoing
	// This need fixing !
	while( actionStream >> action ) {
		int col,row;
		if(Spread == action) {
			actionStream >> col >> row >> claimer; 
			gameBoard().placePiece(col,row,claimer);
		} else if (Split == action) {
			gameBoard().placePiece(gameMove.f_col,gameMove.f_row, player);
		}
	}
	return;
	

}

void Ataxx::placePieces() {
	gameBoard().setBoard(columns(),rows());
	gameBoard().placePiece(1,1,Player1);
	gameBoard().placePiece(columns(),1,Player2);
	gameBoard().placePiece(1,rows(),Player2);
	gameBoard().placePiece(columns(),rows(),Player1);
}

inline bool vectorDistance(const Move &gameMove, int maxDistance) {
	if(std::abs(gameMove.t_col-gameMove.f_col) > maxDistance) return false;
	else if(std::abs(gameMove.t_row-gameMove.f_row) > maxDistance) return false;
	return true;
}

bool Ataxx::legalMove( const Move &gameMove ){
	bool illegal = false;
	std::string error;
	int pieceOwner = gameBoard().getOccupancy(gameMove.f_col,gameMove.f_row);
	int targetField = gameBoard().getOccupancy(gameMove.t_col,gameMove.t_row);
	if(currentPlayer() != pieceOwner) {
		illegal = true;
		if(!AI)error = "Cannot move other players piece";
	}
	else if( None != targetField ) {
		illegal = true;
		if(!AI)error = "Other Player in the way!";
	}
	else if(!vectorDistance(gameMove,maxJump)) {
		illegal = true;
		if(!AI)error = "Jump too long!";
	}
	// TODO: Should derived game handle obstructed fields?
	// Game piece of certain type could destroy obstructions maybe
	if (illegal && !AI) {
		std::cout << "Illegal Move";
		if(debugger->debug()) {
			std::cout << ": " << error; 
		}
		std::cout << std::endl;
	}
	return !illegal;
}

bool Ataxx::winCondition() {
	if(getLegalMoves()->empty()) {
		return true;
	}
	return false;
}

void Ataxx::getPossibleDestinations(std::vector<std::pair<int,int> > &possibleDestinations, std::pair<int,int> &location){
	// possible moves for Ataxx, is any vector distance length 1 and 2, so all
	// 5*5 fields around a piece are possible, apart from the current piece location.
	// But we will let legal move throw that move out, and save 25 int comparisons.
	for(int i = -2; i <= 2 ; ++i ) {
		for( int j = -2 ; j <= 2 ; ++j ) {
			possibleDestinations.push_back(std::pair<int,int>(location.first+i,location.second+j));
		}
	}
}


